#ifndef System_First
#define System_First
#ifdef __GNUG__
#pragma interface
#endif

#include "Object.h"
#include "Time.h"
#include "Main.h"
#include "ET_stdio.h"

struct unixptty;
struct PttyChars;
class SeqCollection;
class SysEvtHandler;
class FileHandler;
class SignalHandler;
class System;
class Timer;
class PttyImpl;

extern System *gSystem;
extern int gDebug;
extern bool
	gInMain,
	gQuitApp;
extern const char
	*gEtDir,
	*gProgname,
	*gProgPath;

extern void ETInit(int argc, char **argv);
extern void InitSystem();

//---- System ------------------------------------------------------------------

class System : public Object {
public:
	MetaDef(System);
	System(const char *name= "GENERIC");
	virtual ~System();

	//---- Misc
	const char *AsString();
	virtual bool Init();
	const char *GetErrorStr();
	virtual const char *GetError();
	void RemoveOnExit(Object*);

	//---- EventLoop
	virtual void Control();
	void ExitControl();
	void InnerLoop();
	virtual void DispatchOneEvent();

	//---- handling of system events
	virtual void AddFileHandler(FileHandler*);
	virtual FileHandler *RemoveFileHandler(FileHandler*);
	virtual void AddSignalHandler(SignalHandler*);
	virtual SignalHandler *RemoveSignalHandler(SignalHandler*);
	virtual void AddCleanupObject(Object*);
	void Remove();

	//---- Processes
	virtual int Exec(const char *shellcmd);
	virtual FILE *OpenPipe(const char *command, const char *mode);
	virtual int ClosePipe(FILE *pipe);
	virtual void Exit(int code, bool mode= TRUE);
	virtual void Wait(unsigned int);
	virtual void Abort(int code= 0);
	virtual int GetPid();

	//---- Directories
	virtual void *MakeDirectory(const char *name);
	virtual void FreeDirectory(void *dirp);
	virtual const char *GetDirEntry(void *dirp);
	virtual bool ChangeDirectory(const char *path);
	virtual const char *WorkingDirectory();
	virtual const char *HomeDirectory();
	virtual const char *DirName(const char *pathname);

	//---- Paths & Files
	virtual bool ExpandPathName(char *patbuf, int buflen);
			// expand the metacharacters in Pat as in the shell
	virtual bool AccessPathName(const char *path, int mode= 0);
	virtual void Rename(const char *from, const char *to);
	virtual int GetPathInfo(const char *path, u_long *id, u_long *size, u_long *flags, u_long *modtime);

	//---- environment manipulation
	virtual void Setenv(const char *name, const char *value);
		// set environment variable name to value
	virtual void Unsetenv(const char *name);
		// remove environment variable
	virtual const char *Getenv(const char*);
	virtual const char *GetEnvAt(int ix);

	//---- Time & Date
	virtual Time Now();
	virtual void AddTimer(Timer*);
	virtual bool RemoveTimer(Timer*);
	Timer *&TimerHead(bool sync);
	long NextTimeout(Timer *head);
	
	//---- Dynamic Loading
	virtual Object *Load(const char *progname, const char *name);

	//---- IAC
	virtual int OpenConnection(const char *server, const char *service);
	virtual int AnnounceTcpService(const char *service);
	virtual int AnnounceUnixService(const char *server);
	virtual int AcceptConnection(int sock);

	//---- Pseudo TTYs
	virtual PttyImpl *MakePttyImpl();

protected:
	//---- handling of system events
	void remove(SeqCollection *&oc);

protected:
	bool done;
	char *errorstr;
	const char *name;
	bool environIsCopied;
	int level;

	Timer *syncTimers, *asyncTimers;

	SeqCollection *fileHandler;
	SeqCollection *signalHandler;
	SeqCollection *cleanupList;
	SeqCollection *onExitList;

public:
	static bool anyremoved;
};

inline const char *System::GetErrorStr()
	{ return errorstr; }
inline Timer *&System::TimerHead(bool sync)
	{ return sync ? syncTimers : asyncTimers; }

#endif
